﻿using MongoDB;
using MongoDB.Configuration;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using WindowsFormsAcess.OLEDB;

namespace WindowsFormsAcess
{
    /// <summary>
    /// 性能测试
    /// </summary>
    public partial class DBPerformance : Form
    {
        #region 初始化和构造
        /// <summary>
        /// MSSQL
        /// </summary>
        private OLEDB.DBFairy dbFairyMSSQL = null;
        /// <summary>
        /// ORACLE
        /// </summary>
        private OLEDB.DBFairy dbFairyOracle = null;
        /// <summary>
        /// ACESS
        /// </summary>
        private OLEDB.DBFairy dbFairyAcess = null;
        /// <summary>
        /// Mongo
        /// </summary>
        MongoConfigurationBuilder dbFairyMongo = null;
        /// <summary>
        /// 显示顺序的标签
        /// </summary>
        List<Label> qeueLabel = new List<Label>();
        /// <summary>
        /// 构造数据库
        /// </summary>
        public DBPerformance()
        {
            InitializeComponent();

            string connectionString = System.Configuration.ConfigurationManager.ConnectionStrings["WindowsFormsAcess.Properties.Settings.OLEDBConnectionString"].ConnectionString;
            string oracleCNString = System.Configuration.ConfigurationManager.ConnectionStrings["WindowsFormsAcess.Properties.Settings.OracleConnectionString"].ConnectionString;
            string accessCNString = System.Configuration.ConfigurationManager.ConnectionStrings["WindowsFormsAcess.Properties.Settings.AccessConnectionString"].ConnectionString;

            accessCNString = @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=E:\OSChina\Source\Repos\Thenu.TinyHourseLib\THenu.TinyHourseLib\DataBaseAcess\WindowsFormsAcess\App_Data\Student.mdb";
            dbFairyMSSQL = new OLEDB.DBFairy(connectionString, DBFairy.DBType_MSSQL, false);
            dbFairyOracle = new OLEDB.DBFairy(oracleCNString, DBFairy.DBType_Oracle, false);
            dbFairyAcess = new OLEDB.DBFairy(accessCNString, DBFairy.DBType_ACCESS, true);
            // _DBConfig.ConnectionString("Server=127.0.0.1");
            dbFairyMongo = new MongoConfigurationBuilder();
            dbFairyMongo.ConnectionString("Server=127.0.0.1");
        }
        /// <summary>
        /// 插入语句
        /// </summary>
        public string AppendString = "INSERT INTO Students (ID,STUNO,NAME,AGE,SEX,DESCRIPTION ) VALUES (?,?,?,?,?,?)";
        /// <summary>
        /// 更新语句
        /// </summary>
        public string UpdateString = "Update Students SET DESCRIPTION = ? Where NAME = ?";
        /// <summary>
        /// 处理
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void comboBoxCommondType_SelectedIndexChanged(object sender, EventArgs e)
        {

        }
        /// <summary>
        /// MSSQL 计时器
        /// </summary>
        private System.Diagnostics.Stopwatch stopWatch = new System.Diagnostics.Stopwatch();
        /// <summary>
        ///  Oracle 计时器
        /// </summary>
        private System.Diagnostics.Stopwatch stopWatchOracle = new System.Diagnostics.Stopwatch();
        /// <summary>
        ///  Acess 计时器
        /// </summary>
        private System.Diagnostics.Stopwatch stopWatchAcess = new System.Diagnostics.Stopwatch();
        /// <summary>
        ///  Mongo 计时器
        /// </summary>
        private System.Diagnostics.Stopwatch stopWatchMongo = new System.Diagnostics.Stopwatch();
        /// <summary>
        /// 开始
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnBegin_Click(object sender, EventArgs e)
        {
            // 恢复初始计数
            completed = 0;
            lblMSSQL.ForeColor = lblAceesss.ForeColor = lblOracle.ForeColor = lblMongo.ForeColor = Color.Black;
            int i = 1;
            qeueLabel.ForEach(p => { p.Text = i.ToString(); i++; });

            // 根据选择情况决定是否执行
            if (checkBoxAcess.Checked)
            {
                richTextBoxMSSQL.Clear();
                this.numericUpDownAcess.Value = 0;
                bgAcessWorker.RunWorkerAsync();
            }
            if (checkBoxMSSQL.Checked)
            {
                richTextBoxAcess.Clear();
                this.numericUpDownMSSQL.Value = 0;
                bgMSWorker.RunWorkerAsync();
            }
            if (checkBoxOracle.Checked)
            {
                richTextBoxOracle.Clear();
                this.numericUpDownOracle.Value = 0;
                bgOracleWorker.RunWorkerAsync();
            }
            if (checkBoxMongo.Checked)
            {
                richTextBoxMongo.Clear();
                this.numericUpDownMongo.Value = 0;
                bgMongoWorker.RunWorkerAsync();
            }
        }
        /// <summary>
        /// 完成顺序
        /// </summary>
        int completed = 0;
        /// <summary>
        /// 颜色初始化
        /// </summary>
        Color[] colorsGrade = { Color.DarkGreen, Color.DodgerBlue, Color.DarkGoldenrod, Color.DarkCyan };
        /// <summary>
        /// 初始化颜色表示
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void DBPerformance_Load(object sender, EventArgs e)
        {
            qeueLabel.Add(lblFirst);
            qeueLabel.Add(lblSecond);
            qeueLabel.Add(lblThird);
            qeueLabel.Add(lblFourth);

            lblFirst.BackColor = colorsGrade[0];
            lblSecond.BackColor = colorsGrade[1];
            lblThird.BackColor = colorsGrade[2];
            lblFourth.BackColor = colorsGrade[3];

            numericUpDownMSSQL.Maximum = numericUpDownAcess.Maximum = numericUpDownMongo.Maximum
            = numericUpDownOracle.Maximum = txtCount.Maximum = int.MaxValue;


            DisplayAmount();

        }
        /// <summary>
        /// 查询各个数据库中的记录数量
        /// </summary>
        private void DisplayAmount()
        {
            int nMSSQL = GetSQLAmount(dbFairyMSSQL);
            int nOracle = GetSQLAmount(dbFairyOracle);
            int nAcess = GetSQLAmount(dbFairyAcess);
            int nMongo = GetSQLAmount(dbFairyMongo);
            
            richTextBoxMSSQL.AppendText(string.Format("Current Amount:{0,10}\r\n", nMSSQL));
            richTextBoxOracle.AppendText(string.Format("Current Amount:{0,10}\r\n", nOracle));
            richTextBoxAcess.AppendText(string.Format("Current Amount:{0,10}\r\n", nAcess));
            richTextBoxMongo.AppendText(string.Format("Current Amount:{0,10}\r\n", nMongo));
        }
        /// <summary>
        /// 获取NOSQL数据库记录数量
        /// </summary>
        /// <param name="dbFairyMongo"></param>
        /// <returns></returns>
        private int GetSQLAmount(MongoConfigurationBuilder dbFairyMongo)
        {
            using (Mongo dbMongo = new MongoDB.Mongo(dbFairyMongo.BuildConfiguration()))
            {
                dbMongo.Connect();
                var db = dbMongo.GetDatabase("PerformanceMongo");
                var infoCollection = db.GetCollection("Student");
                return (int)infoCollection.Count(new Document());
            }
        }
        /// <summary>
        /// 获取SQL数据库数量
        /// </summary>
        /// <param name="dbFairyMSSQL"></param>
        /// <returns></returns>
        private int GetSQLAmount(DBFairy dbFairyMSSQL)
        {
            int nAmount = 0;
            nAmount = Convert.ToInt32(dbFairyMSSQL.ExecuteScalar("SELECT COUNT(*) FROM STUDENTS"));
            return nAmount;

        }
        #endregion

        #region 执行任务
        /// <summary>
        /// 执行插入操作
        /// </summary>
        /// <param name="i"></param>
        /// <param name="dbFairy"></param>
        /// <returns></returns>
        private int DoAppendDBWork(int i, DBFairy dbFairy)
        {
            System.Data.OleDb.OleDbParameter id = null;
            if (dbFairy.DBType == DBFairy.DBType_Oracle)
            {
                id = new System.Data.OleDb.OleDbParameter("ID", DBFairy.DotNetToOracleGUID(Guid.NewGuid().ToString()));
            }
            else
            {
                id = new System.Data.OleDb.OleDbParameter("ID", Guid.NewGuid().ToString());
            }
            System.Data.OleDb.OleDbParameter[] paras = new System.Data.OleDb.OleDbParameter[]{
              
                    id,
                    new System.Data.OleDb.OleDbParameter("STUNO", 2009430+i),
                    new System.Data.OleDb.OleDbParameter("NAME", "姓名"+i),
                    new System.Data.OleDb.OleDbParameter("AGE",20+ i%2),
                    new System.Data.OleDb.OleDbParameter("SEX", i%2),
                    new System.Data.OleDb.OleDbParameter("DESCRIPTION", DateTime.Now.ToShortDateString())
                    };
            return dbFairy.ExecuteNonQuery(AppendString, paras);
        }
        #endregion

        #region MS SQL
        private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (!e.Cancelled && e.Error == null)
            {
                stopWatch.Stop();

                numericUpDownMSSQL.Value = stopWatch.ElapsedMilliseconds;

                lblMSSQL.ForeColor = colorsGrade[completed];
                CompletedTask("MS SQL");
                completed++;

            }

        }

        private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            try
            {
                stopWatch.Reset();
                stopWatch.Start();
                int count = Convert.ToInt32(txtCount.Value);
                for (int i = 0; i < count; i++)
                {

                    int result = DoAppendDBWork(i, dbFairyMSSQL);
                    if (result < 1)
                    {
                        string desc = string.Empty;
                        if (i % 100 == 0)
                            bgMSWorker.ReportProgress(i, desc);
                    }
                    else
                    {
                        if (i % 100 == 0)
                            bgMSWorker.ReportProgress(i);
                    }
                }
            }
            catch (Exception ex)
            {

                throw ex;
            }
        }



        private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            try
            {
                if (e.UserState != null)
                {
                    richTextBoxMSSQL.AppendText("Error: At" + e.ProgressPercentage.ToString() + Environment.NewLine);
                }
                else
                {
                    richTextBoxMSSQL.AppendText(e.ProgressPercentage.ToString() + Environment.NewLine);
                }
                richTextBoxMSSQL.SelectionStart = richTextBoxMSSQL.Text.Length;
                this.richTextBoxMSSQL.ScrollToCaret();
                numericUpDownMSSQL.Value = stopWatch.ElapsedMilliseconds;
            }
            catch (Exception ex)
            {
                throw ex;
            }

        }
        #endregion

        #region Oracle
        private void bgOracleWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            stopWatchOracle.Reset();
            stopWatchOracle.Start();

            int count = Convert.ToInt32(txtCount.Value);
            for (int i = 0; i < count; i++)
            {

                int result = DoAppendDBWork(i, dbFairyOracle);
                if (result < 1)
                {
                    string desc = string.Empty;
                    bgOracleWorker.ReportProgress(i, desc);
                }
                else
                {
                    if (i % 100 == 0)
                        bgOracleWorker.ReportProgress(i);
                }
            }
        }

        private void bgOracleWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            try
            {
                if (e.UserState != null)
                {
                    richTextBoxOracle.AppendText("Error: At" + e.ProgressPercentage.ToString() + Environment.NewLine);
                    richTextBoxOracle.AppendText(e.UserState.ToString());
                }
                else
                {
                    richTextBoxOracle.AppendText(e.ProgressPercentage.ToString() + Environment.NewLine);
                }
                richTextBoxOracle.SelectionStart = richTextBoxOracle.Text.Length;

                this.richTextBoxOracle.ScrollToCaret();
                numericUpDownOracle.Value = stopWatchOracle.ElapsedMilliseconds;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        private void bgOracleWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (!e.Cancelled && e.Error == null)
            {
                stopWatch.Stop();

                numericUpDownOracle.Value = stopWatchOracle.ElapsedMilliseconds;

                lblOracle.ForeColor = colorsGrade[completed];
                CompletedTask("Oracle");
                completed++;


            }
        }
        #endregion

        #region Acess
        private void bgAcessWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            stopWatchAcess.Reset();
            stopWatchAcess.Start();
            int count = Convert.ToInt32(txtCount.Value);
            for (int i = 0; i < count; i++)
            {

                int result = DoAppendDBWork(i, dbFairyAcess);
                if (result < 1)
                {
                    string desc = string.Empty;
                    bgAcessWorker.ReportProgress(i, desc);
                }
                else
                {
                    if (i % 100 == 0)
                        bgAcessWorker.ReportProgress(i);
                }
            }
        }

        private void bgAcessWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            try
            {
                if (e.UserState != null)
                {
                    richTextBoxAcess.AppendText("Error: At" + e.ProgressPercentage.ToString() + Environment.NewLine);
                    richTextBoxAcess.AppendText(e.UserState.ToString());
                }
                else
                {
                    richTextBoxAcess.AppendText(e.ProgressPercentage.ToString() + Environment.NewLine);
                }
                richTextBoxAcess.SelectionStart = richTextBoxAcess.Text.Length;
                this.richTextBoxAcess.ScrollToCaret();

                numericUpDownAcess.Value = stopWatchAcess.ElapsedMilliseconds;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        private void bgAcessWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (!e.Cancelled && e.Error == null)
            {
                stopWatchAcess.Stop();

                numericUpDownAcess.Value = stopWatchAcess.ElapsedMilliseconds;
                lblAceesss.ForeColor = colorsGrade[completed];
                CompletedTask("Acess");
                completed++;
            }
        }
        /// <summary>
        /// 设置完成
        /// </summary>
        /// <param name="p"></param>
        private void CompletedTask(string pName)
        {
            qeueLabel[completed].Text = pName;
        }
        #endregion

        #region Mongo
        /// <summary>
        /// bgMongoWorker_DoWork
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void bgMongoWorker_DoWork(object sender, DoWorkEventArgs e)
        {

            try
            {
                stopWatchMongo.Restart();

                int count = Convert.ToInt32(txtCount.Value);
                for (int i = 0; i < count; i++)
                {
                    int result = MongoExecuteNoquery(i);
                    if (result < 1)
                    {
                        string desc = string.Empty;
                        bgMongoWorker.ReportProgress(i, desc);
                    }
                    else
                    {
                        if (i % 100 == 0)
                            bgMongoWorker.ReportProgress(i);
                    }
                }
            }
            catch (Exception ex)
            {

                throw ex;
            }
        }
        /// <summary>
        /// 完成
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void bgMongoWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (!e.Cancelled && e.Error == null)
            {
                stopWatchMongo.Stop();

                numericUpDownMongo.Value = stopWatchMongo.ElapsedMilliseconds;

                lblMongo.ForeColor = colorsGrade[completed];
                CompletedTask("Mongo");
                completed++;
            }
        }
        /// <summary>
        /// 进度通知
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void bgMongoWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            try
            {
                if (e.UserState != null)
                {


                    richTextBoxMongo.AppendText("Error: At" + e.ProgressPercentage.ToString() + Environment.NewLine);
                }
                else
                {
                    richTextBoxMongo.AppendText(e.ProgressPercentage.ToString() + Environment.NewLine);
                }
                richTextBoxMongo.SelectionStart = richTextBoxMongo.Text.Length;
                this.richTextBoxMongo.ScrollToCaret();
                numericUpDownMongo.Value = stopWatchMongo.ElapsedMilliseconds;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        /// <summary>
        /// 执行查询
        /// </summary>
        /// <param name="i"></param>
        /// <returns></returns>
        public int MongoExecuteNoquery(int i)
        {

            using (Mongo dbMongo = new MongoDB.Mongo(dbFairyMongo.BuildConfiguration()))
            {
                try
                {
                    dbMongo.Connect();

                    var db = dbMongo.GetDatabase("PerformanceMongo");
                    var infoCollection = db.GetCollection("Student");
                    List<KeyValuePair<string, object>> listvalue = new List<KeyValuePair<string, object>>(){
                      new  KeyValuePair<string, object>("STUNO",2009430 + i),
                      new  KeyValuePair<string, object>("NAME","姓名" + i),
                      new  KeyValuePair<string, object>("AGE",20 + i % 2),
                      new  KeyValuePair<string, object>("SEX",i % 2),
                      new  KeyValuePair<string, object>("DESCRIPTION",DateTime.Now.ToShortDateString() ),
                    };
                    infoCollection.Insert(new Document(listvalue));
                    return 1;
                }
                catch
                {
                    return 0;
                }
                finally
                {
                    dbMongo.Disconnect();
                }
            }
        }
        #endregion
    }
}
